import os
import cv2
import imageio
from PyQt5.QtCore import QThread, pyqtSignal

class ExportGifThread(QThread):
    progress_signal = pyqtSignal(int)
    finished_signal = pyqtSignal(str)
    error_signal = pyqtSignal(str)

    def __init__(self, video_path, start_frame, end_frame, width, height, frames, fps, optimize=False):
        super().__init__()
        self.video_path = video_path
        self.start_frame = start_frame
        self.end_frame = end_frame
        self.width = width
        self.height = height
        self.frames = frames
        self.fps = fps
        self.optimize = optimize
        self.is_cancelled = False

    def run(self):
        try:
            cap = cv2.VideoCapture(self.video_path)
            if not cap.isOpened():
                self.error_signal.emit("无法打开视频文件")
                return

            total_frames = self.end_frame - self.start_frame
            frame_interval = max(1, total_frames // self.frames)

            gif_frames = []
            current_frame = 0
            while True:
                if self.is_cancelled:
                    break

                ret, frame = cap.read()
                if not ret:
                    break
                if self.start_frame <= current_frame < self.end_frame and current_frame % frame_interval == 0:
                    frame = cv2.resize(frame, (self.width, self.height))
                    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                    gif_frames.append(frame)
                    self.progress_signal.emit(current_frame - self.start_frame)
                current_frame += 1

            cap.release()

            if not self.is_cancelled:
                gif_path = os.path.splitext(self.video_path)[0] + ".gif"
                if self.optimize:
                    with imageio.get_writer(gif_path, mode='I', fps=self.fps) as writer:
                        for frame in gif_frames:
                            writer.append_data(frame)
                else:
                    imageio.mimsave(gif_path, gif_frames, fps=self.fps)
                self.finished_signal.emit(gif_path)
        except Exception as e:
            self.error_signal.emit(str(e))

    def cancel(self):
        self.is_cancelled = True